             package com.java.diagnostics.visualizer.gc.realtimeV2.parser;
             
             import com.java.diagnostics.visualizer.data.TupleDataBuilder;
             import com.java.diagnostics.visualizer.data.axes.AxisPair;
             import com.java.diagnostics.visualizer.factory.DataFactory;
             import com.java.diagnostics.visualizer.gc.realtime.util.Messages;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData.TableField;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData.TableType;
             import org.xml.sax.Attributes;
             
             public class HeartBeatParser
               extends GCEventParser
             {
               private static final String QUANTUMCOUNT = "quantumcount";
               final HeartBeatSummaryParser summaryParser;
               private HeartBeatSummaryParser currentParser;
               int cycleQuantaCount;
               int totalQuantaCount;
               long totalPauseTimeMicros;
               TupleDataBuilder quantaPerHeartbeat;
               StoredPoints points = new StoredPoints(1);
               
               HeartBeatParser(CommonData commonData, DataFactory factory, AxisPair timePair, AxisPair discreteNumberPair, AxisPair discreteTimePair, AxisPair activityPair, boolean interpolateTimestamps)
               {
                 super(commonData);
                 this.summaryParser = new HeartBeatSummaryParser(
                   commonData, 
                   factory, 
                   timePair, 
                   discreteNumberPair, 
                   discreteTimePair, 
                   activityPair, 
                   interpolateTimestamps);
                 this.quantaPerHeartbeat = factory.createTupleData("RealtimeLabels.quanta.per.heartbeat", Messages.getString("RealtimeLabels.quanta.per.heartbeat"), discreteNumberPair);
                 TupleMetaData quantaPerHeartbeatMetaData = new TupleMetaData(
                   TupleMetaData.TableType.ARITHMETIC, new TupleMetaData.TableField[] {
                   TupleMetaData.TableField.MEAN, TupleMetaData.TableField.MIN, TupleMetaData.TableField.MAX });
                 this.quantaPerHeartbeat.setTupleMetaData(quantaPerHeartbeatMetaData);
               }
               
               boolean startElement(String uri, String localName, String name, Attributes atts, String comment)
               {
                 boolean ret = true;
                 if (this.currentParser != null) {
                   ret = this.currentParser.startElement(uri, localName, name, atts, comment);
                 } else if (name.equals("summary")) {
                   long count = CommonData.convertPositiveInteger(atts.getValue("quantumcount"));
                   if (count >= 0L) {
                     this.points.storePoint(this.quantaPerHeartbeat, count, comment);
                     this.cycleQuantaCount = ((int)(this.cycleQuantaCount + count));
                     this.totalQuantaCount = ((int)(this.totalQuantaCount + count));
                     this.currentParser = this.summaryParser;
                     this.currentParser.quantumCount = count;
                   }
                 } else {
                   ret = super.startElement(uri, localName, name, atts, comment);
                 }
                 if (ret) {
                   return true;
                 }
                 complete();
                 return false;
               }
               
               boolean endElement(String uri, String localName, String name, String comment)
               {
                 if (this.currentParser != null) {
                   if (this.currentParser.endElement(uri, localName, name, comment)) {
                     return true;
                   }
                   this.currentParser = null;
                 }
                 if (super.endElement(uri, localName, name, comment)) {
                   return true;
                 }
                 complete();
                 return false;
               }
               
               private void complete() {
                 if (this.summaryParser.quantumCount > 0L) {
                   this.totalPauseTimeMicros += this.summaryParser.meanPauseMicros * this.summaryParser.quantumCount;
                 }
                 
                 this.commonData.setXAxis(this.timeMicros / 1000.0D);
                 this.points.complete();
                 
                 this.commonData.completeGCEvent("heartbeat", 0, this.id, this.initialComment);
               }
               
               void init(long micros, String initialComment, long intervalMicros)
               {
                 super.init(micros, initialComment, intervalMicros);
                 this.summaryParser.init(micros, initialComment, intervalMicros);
               }
             }


